package com.liuyi.mybatisplus.plus.base;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.IService;
import com.liuyi.mybatisplus.plus.condition.QueryCondition;
import com.liuyi.mybatisplus.plus.condition.QueryWrapperAnalysis;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author Mr.fmy
 * @version 1.0.0
 * @ClassName IBaseService
 * @Description TODO Mybatis-plus IService 继承接口
 * @createTime 2019/9/26 15:06
 */
public interface IBaseService<T> extends IService<T> {


    /**
     * {@linkplain QueryCondition 条件数据构造}
     */
    default QueryWrapper<T> analysisQ(QueryCondition conditio, Map<String, Class> table) {
        return QueryWrapperAnalysis.analysis(q(), conditio, table);
    }

    /**
     * {@linkplain QueryCondition 条件数据构造}
     */
    default QueryWrapper<T> analysisQ(QueryCondition conditio) {
        Class<T> entityClass = getEntityClass();
        Map<String, Class> tableMap = null;
        if (entityClass != null) {
            tableMap = CollUtil.newHashMap();
            tableMap.put("this", entityClass);
        }
        return QueryWrapperAnalysis.analysis(q(), conditio, tableMap);
    }

    default Class<T> getEntityClass() {
        return null;
    }

    @SuppressWarnings("unchecked")
    default <M extends BaseMapper<T>> M getMapper() {
        return (M) getBaseMapper();
    }

    default int count(String colunm, Object value) {
        return this.count(q().eq(colunm, value));
    }

    /**
     * 公用的 效验并生成主键是否存在
     *
     * @param primarySupplier 生成主键的值的 函数式编程
     * @param countFunction   效验主键是否存在的 函数式编程
     *                        <p>
     *                        参考用法： this.primaryGenerate(() -> RandomUtil.randomNumbers(9), (primary) -> this.count(UserSign.USER_NUMBER, primary))
     *                        this 单指当前 IService
     *                        </p>
     */
    default <R> R primaryGenerate(Supplier<R> primarySupplier, Function<R, Integer> countFunction) {
        R primary = primarySupplier.get();
        while (countFunction.apply(primary) > 0) {
            primary = primarySupplier.get();
        }
        return primary;
    }

    /**
     * <p>
     * {@linkplain #primaryGenerate(Supplier, Function)} 的精简版
     * 参考用法： this.primaryGenerate(() -> RandomUtil.randomNumbers(9),UserSign.USER_NUMBER)
     * </p>
     */
    default <R> R primaryGenerate(Supplier<R> primarySupplier, String colunm) {
        return primaryGenerate(primarySupplier, (primary) -> count(colunm, primary));
    }

    default <R> R getObj(String colunm, Object value, String getColunm, Function<Object, R> function) {
        R obj = getObj(q().eq(colunm, value).select(getColunm), function);
        return obj;
    }

    default QueryWrapper<T> q() {
        return Wrappers.query();
    }

    default UpdateWrapper<T> u() {
        return Wrappers.update();
    }

    default <V> List<V> toBeans(List<T> datas, Class<V> c) {
        List<V> beans = new ArrayList<>(datas.size());
        datas.forEach(item -> beans.add(BeanUtil.toBean(item, c)));
        return beans;
    }

    default <V> V toBean(T data, Class<V> c) {
        return BeanUtil.toBean(data, c);
    }
}
